package me.flyray.bsin.infrastructure.biz.paychannel.wxpay.payway;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.v3.util.PemUtils;
import lombok.extern.slf4j.Slf4j;
import me.flyray.bsin.domain.entity.PayChannelConfig;
import me.flyray.bsin.infrastructure.biz.paychannel.PayChannelConfigBiz;
import me.flyray.bsin.infrastructure.biz.paychannel.wxpay.WxPayPaymentService;
import me.flyray.bsin.infrastructure.utils.ApiResBuilder;
import me.flyray.bsin.payment.common.AbstractRes;
import me.flyray.bsin.payment.channel.wxpay.model.UnifyOrderReq;
import me.flyray.bsin.payment.channel.wxpay.model.RefundUnifyReq;
import me.flyray.bsin.payment.channel.wxpay.WxRefundRes;
import me.flyray.bsin.payment.enums.PayChannelInterfaceEnum;
import me.flyray.bsin.payment.enums.PayMerchantModeEnum;
import me.flyray.bsin.payment.channel.wxpay.model.WxPayV3OrderRequestModel;
import me.flyray.bsin.payment.channel.wxpay.WxLiteOrderRes;
import me.flyray.bsin.payment.channel.wxpay.WxPayV3Util;
import me.flyray.bsin.payment.channel.wxpay.WxServiceUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;

/*
 * 微信 小程序
 * @author leonard
 * @date 2025/07/24 14:05
 */
@Component("wxPayPaymentByLiteV3Service") // Service Name需保持全局唯一性
@Slf4j
public class WxLite extends WxPayPaymentService {

  @Autowired protected PayChannelConfigBiz payChannelConfigBiz;

  /**
   * 小程序支付
   *
   * @param request
   */
  @Override
  public AbstractRes pay(UnifyOrderReq request) throws Exception {
    log.info("开始处理微信小程序支付，outOrderNo: {}", request.getOutOrderNo());
    // 获取参数配置
    AtomicBoolean isCache = new AtomicBoolean(true);
    PayChannelConfig payChannelConfig =
        payChannelConfigBiz.queryPayChannelConfig(
            request.getBizRoleAppId(),
            // 相当于商户号或者平台编号
            request.getBizRoleTypeNo(),
            PayChannelInterfaceEnum.WXPAY.getCode(),
            request.getMerchantPayMode(),
            isCache);
    request.setPayChannelConfigNo(payChannelConfig.getSerialNo());
    WxServiceUtil wxServiceWrapper = payChannelConfigBiz.getWxServiceWrapper(payChannelConfig);
    WxPayService wxPayService = wxServiceWrapper.getWxPayService();

    if (!isCache.get()) {
      log.info("缓存中未查询到参数配置，从数据库中查询，重新写入缓存。。。");
      payChannelConfigBiz.setPayChannelConfigMapper(payChannelConfig);
    }
    // 构造WX_JSAPI 请求数据
    WxPayV3OrderRequestModel wxpayV3OrderRequestModel =
        buildV3OrderRequestModel(
            request, wxServiceWrapper.getNotifyUrl(), wxPayService, payChannelConfig);
    // 构造函数响应数据
    WxLiteOrderRes res = ApiResBuilder.buildSuccess(WxLiteOrderRes.class);
    //    ChannelRetMsg channelRetMsg = new ChannelRetMsg();
    //    res.setChannelRetMsg(channelRetMsg);

    // 调起上游接口：
    try {
      String payInfo =
          WxPayV3Util.commonReqWx(
              wxpayV3OrderRequestModel,
              wxPayService,
              PayMerchantModeEnum.SPECIAL_MERCHANT_MODE
                      .getCode()
                      .equals(request.getMerchantPayMode())
                  ? true
                  : false,
              WxPayConstants.TradeType.JSAPI,
              (JSONObject wxRes) -> {
                String appId = null;

                // 特约商户
                if (PayMerchantModeEnum.SPECIAL_MERCHANT_MODE
                    .getCode()
                    .equals(request.getMerchantPayMode())) {
                  appId =
                      StringUtils.defaultIfEmpty(
                          wxpayV3OrderRequestModel.getSubAppid(),
                          wxpayV3OrderRequestModel.getIsvAppid());
                }
                // 普通商户
                else {
                  appId = wxpayV3OrderRequestModel.getNormalAppid();
                }

                // 使用wxjava公共函数，生成
                WxPayUnifiedOrderV3Result wxPayUnifiedOrderV3Result =
                    new WxPayUnifiedOrderV3Result();
                wxPayUnifiedOrderV3Result.setPrepayId(wxRes.getString("prepay_id"));
                try {

                  FileInputStream fis =
                      new FileInputStream(wxPayService.getConfig().getPrivateKeyPath());

                  WxPayUnifiedOrderV3Result.JsapiResult jsapiResult =
                      wxPayUnifiedOrderV3Result.getPayInfo(
                          TradeTypeEnum.JSAPI, appId, null, PemUtils.loadPrivateKey(fis));

                  JSONObject jsonRes = (JSONObject) JSON.toJSON(jsapiResult);
                  jsonRes.put("package", jsonRes.getString("packageValue"));
                  jsonRes.remove("packageValue");

                  try {
                    fis.close();
                  } catch (IOException e) {
                  }

                  return JSON.toJSONString(jsonRes);

                } catch (FileNotFoundException e) {
                  return null;
                }
              });

      res.setPayInfo(payInfo);

      //      // 支付中
      //      channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
    } catch (WxPayException e) {
      //      // 明确失败
      //      channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
      //      WxPayUtil.commonSetErrInfo(channelRetMsg, e);
      throw e;
    }
    return res;
  }

  /**
   * 微信小程序退款
   *
   * @param request
   */
  @Override
  public AbstractRes refund(RefundUnifyReq request) throws Exception {
    log.info("开始处理微信小程序退款，outRefundNo: {}", request.getOutRefundNo());
    // 获取支付渠道配置
    AtomicBoolean isCache = new AtomicBoolean(true);
    PayChannelConfig payChannelConfig =
        payChannelConfigBiz.queryPayChannelConfig(request.getPayChannelConfigNo(), isCache);

    WxServiceUtil wxServiceWrapper = payChannelConfigBiz.getWxServiceWrapper(payChannelConfig);
    WxPayService wxPayService = wxServiceWrapper.getWxPayService();

    if (!isCache.get()) {
      log.info("缓存中未查询到参数配置，从数据库中查询，重新写入缓存。。。");
      payChannelConfigBiz.setPayChannelConfigMapper(payChannelConfig);
    }

    // 构造微信退款请求数据
    JSONObject refundRequest = buildWxRefundRequestV3(request, wxServiceWrapper.getNotifyUrl());

    // 构造响应数据
    WxRefundRes res = ApiResBuilder.buildSuccess(WxRefundRes.class);

    try {
      // 调用微信退款V3接口
      log.info(
          "调用微信退款V3接口，outTradeNo: {}, outRefundNo: {}",
          request.getOutTradeNo(),
          request.getOutRefundNo());
      JSONObject refundResult = WxPayV3Util.refundV3(refundRequest, wxPayService);

      if (refundResult != null) {
        // 解析退款结果并填充响应对象
        mapWxRefundResultToResponse(refundResult, res);
        log.info("微信退款成功，refundId: {}, status: {}", res.getRefundId(), res.getStatus());
      } else {
        log.error("微信退款接口返回结果为空，outRefundNo: {}", request.getOutRefundNo());
        throw new RuntimeException("微信退款接口返回结果为空");
      }

    } catch (WxPayException e) {
      log.error(
          "微信退款失败，outRefundNo: {}, wxErrorCode: {}, wxErrorMsg: {}",
          request.getOutRefundNo(),
          e.getErrCode(),
          e.getErrCodeDes(),
          e);
      throw new RuntimeException(
          String.format("微信退款失败，错误码: %s，错误信息: %s", e.getErrCode(), e.getErrCodeDes()));
    }

    return res;
  }
}
